package com.example.reactor.guide.chapter4.functional;

import com.example.reactor.guide.chapter3.repository.Employee;
import com.example.reactor.guide.chapter3.repository.EmployeeRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.reactive.function.server.RouterFunction;
import org.springframework.web.reactive.function.server.ServerResponse;

import static org.springframework.web.reactive.function.BodyExtractors.toMono;
import static org.springframework.web.reactive.function.server.RequestPredicates.GET;
import static org.springframework.web.reactive.function.server.RequestPredicates.POST;
import static org.springframework.web.reactive.function.server.RouterFunctions.route;
import static org.springframework.web.reactive.function.server.ServerResponse.ok;

@Configuration
@RequiredArgsConstructor
public class EmployeeFunctionalConfig {

    private final EmployeeRepository employeeRepository;

    @Bean
    public RouterFunction<ServerResponse> getAllEmployeesRoute() {
        return route(GET("/employees"), req -> ok()
                .body(employeeRepository.findAllEmployees(), Employee.class));
    }

    @Bean
    public RouterFunction<ServerResponse> getEmployeeByIdRoute() {
        return route(GET("/employees/{id}"), req -> ok()
                .body(
                        employeeRepository.findEmployeeById(req.pathVariable("id")),
                        Employee.class));
    }

    @Bean
    public RouterFunction<ServerResponse> updateEmployeeRoute() {
        return route(POST("/employees/update"), req -> req
                .body(toMono(Employee.class))
                .doOnNext(employeeRepository::updateEmployee)
                .then(ok().build()));
    }

    @Bean
    RouterFunction<ServerResponse> composedRoutes() {
        return route(
                GET("/employees"), req -> ok()
                        .body(employeeRepository.findAllEmployees(), Employee.class))

                .and(route(GET("/employees/{id}"), req -> ok()
                        .body(employeeRepository.findEmployeeById(req.pathVariable("id")), Employee.class)))

                .and(route(POST("/employees/update"), req -> req
                        .body(toMono(Employee.class))
                        .doOnNext(employeeRepository::updateEmployee)
                        .then(ok().build())));
    }

}